package som;

import java.util.LinkedList;

import som.funcao_de_vizinhanca.FuncaoDeVizinhancaStrategy;

public class Rede {

	private LinkedList<Neuronio> neuronios;
	private FuncaoDeVizinhancaStrategy funcaoDeVizinhanca;

	public Rede(int quantidadeAtributos, int quantidadeClasses) {

		inicializaNeuronios(quantidadeAtributos, quantidadeClasses);
	}

	private void inicializaNeuronios(int quantidadeAtributos, int quantidadeClasses) {

		neuronios = new LinkedList<>();

		for (int i = 0; i < quantidadeClasses; i++) {

			neuronios.add(new Neuronio(quantidadeAtributos, i));
		}
	}

	public int usaRede(double[] coordenadasDado) {

		int classe = -1;
		double menorDistancia = Double.MAX_VALUE;
		double distancia = -1;

		for (Neuronio neuronio : neuronios) {

			distancia = neuronio.distanciaEuclidiana(coordenadasDado);

			if (distancia < menorDistancia) {
				classe = neuronio.obtemClasse();
				menorDistancia = distancia;
			}
		}
		return classe;
	}

	public void treinaRede(int classeCorreta, double[] coordenadasDado, double taxaAprendizagem) {

		int classeRede = usaRede(coordenadasDado);

		Neuronio neuronio = achaNeuronio(classeRede);

		if (redeAcertou(classeCorreta, classeRede)) {
			neuronio.aproximaNeuronio(coordenadasDado, taxaAprendizagem);

		} else {
			neuronio.afastaNeuronio(coordenadasDado, taxaAprendizagem);
		}

	}

	private Neuronio achaNeuronio(int classeRede) {

		for (Neuronio neuronio : neuronios) {

			if (neuronio.obtemClasse() == classeRede) {

				return neuronio;
			}
		}

		return null;
	}

	private boolean redeAcertou(int classeCorreta, int classeRede) {

		return classeRede == classeCorreta;
	}
	
	public double[] calculaFuncaoDeVizinhanca (){
		return this.funcaoDeVizinhanca.calculaFuncaoDeVizinhanca(this);
	}

	public FuncaoDeVizinhancaStrategy getFuncaoDeVizinhanca() {
		return funcaoDeVizinhanca;
	}

	public void setFuncaoDeVizinhanca(FuncaoDeVizinhancaStrategy funcaoDeVizinhanca) {
		this.funcaoDeVizinhanca = funcaoDeVizinhanca;
	}
}
